package cn.tedu.mall.order.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.pojo.domain.CsmallAuthenticationInfo;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.order.mapper.OmsOrderItemMapper;
import cn.tedu.mall.order.mapper.OmsOrderMapper;
import cn.tedu.mall.order.service.IOmsCartService;
import cn.tedu.mall.order.service.IOmsOrderItemService;
import cn.tedu.mall.order.service.IOmsOrderService;
import cn.tedu.mall.order.utils.IdGeneratorUtils;
import cn.tedu.mall.pojo.order.dto.OrderAddDTO;
import cn.tedu.mall.pojo.order.dto.OrderItemAddDTO;
import cn.tedu.mall.pojo.order.dto.OrderListTimeDTO;
import cn.tedu.mall.pojo.order.dto.OrderStateUpdateDTO;
import cn.tedu.mall.pojo.order.model.OmsCart;
import cn.tedu.mall.pojo.order.model.OmsOrder;
import cn.tedu.mall.pojo.order.model.OmsOrderItem;
import cn.tedu.mall.pojo.order.vo.OrderAddVO;
import cn.tedu.mall.pojo.order.vo.OrderDetailVO;
import cn.tedu.mall.pojo.order.vo.OrderItemListVO;
import cn.tedu.mall.pojo.order.vo.OrderListVO;
import cn.tedu.mall.product.service.order.IForOrderSkuService;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @author BJ
 * @date 2022/11/4 20:22
 */
@DubboService
@Service
@Slf4j
public class OmsOrderServiceImpl implements IOmsOrderService {
    // 库存
    @DubboReference
    private IForOrderSkuService skuService;
    // 购物车
    @Autowired
    private IOmsCartService cartService;
    // 订单
    @Autowired
    private OmsOrderMapper omsOrderMapper;
    // 订单项
    @Autowired
    private OmsOrderItemMapper orderItemMapper;

    @GlobalTransactional
    @Override
    public OrderAddVO addOrder(OrderAddDTO orderAddDTO) {
        // 1.收集订单数据
        OmsOrder order = new OmsOrder();
        BeanUtils.copyProperties(orderAddDTO, order);
        // 1.1补充特殊字段数据
        loadOrder(order);
        // 1.2补充 订单商品列表
        List<OrderItemAddDTO> spus = orderAddDTO.getOrderItems();
        // 若订单中没有商品则无法继续生成订单
        if (spus == null){
            throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,"订单中至少包含一件商品！");
        }
        List<OmsOrderItem> orderItems = new ArrayList<>();
        for (OrderItemAddDTO spu : spus){
            OmsOrderItem orderItem = new OmsOrderItem();
            BeanUtils.copyProperties(spu,orderItem);
            // 补充订单项字段
            orderItem.setId(IdGeneratorUtils.getDistributeId("order_item"));
            orderItem.setOrderId(order.getId());
            orderItems.add(orderItem);
            // 2.减去库存 (Seata 接管全局事务，库存不足，终止事务，发生全局回滚)
            int rows = skuService.reduceStockNum(orderItem.getSkuId(), orderItem.getQuantity());
            if (rows == 0){
                log.warn("商品库存不足！");
                throw new CoolSharkServiceException(ResponseCode.BAD_REQUEST,"商品库存不足！");
            }
            // 3.删除购物车中的sku商品信息
            OmsCart omsCart = new OmsCart();
            omsCart.setUserId(order.getUserId());
            omsCart.setSkuId(orderItem.getSkuId());
            cartService.removeUserCarts(omsCart);
        }
        // 4.新增订单
        omsOrderMapper.addOrder(order);
        // 5.新增订单项（批量新增）
        orderItemMapper.addOrderItemList(orderItems);
        // 6.返还给前端数据
        OrderAddVO addVO = new OrderAddVO();
        addVO.setId(order.getId());
        addVO.setSn(order.getSn());
        addVO.setCreateTime(order.getGmtCreate());
        addVO.setPayAmount(order.getAmountOfActualPay());

        return addVO;
    }

    private void loadOrder(OmsOrder order) {
        // 订单id
        Long id = IdGeneratorUtils.getDistributeId("order");
        order.setId(id);
        // 订单号
        order.setSn(UUID.randomUUID().toString());
        // 用户id
        if (order.getUserId() == null) {
            order.setUserId(getUserId());
        }
        // Time
        LocalDateTime now = LocalDateTime.now();
        order.setGmtOrder(now);
        order.setGmtCreate(now);
        order.setGmtModified(now);
        // pay(实际金额=原价+运费-优惠)
        BigDecimal price = order.getAmountOfOriginalPrice();
        BigDecimal freight = order.getAmountOfFreight();
        BigDecimal discount = order.getAmountOfDiscount();
        BigDecimal decimal = price.add(freight).subtract(discount);
        order.setAmountOfActualPay(decimal);
    }

    // 更新订单状态
    @Override
    public void updateOrderState(OrderStateUpdateDTO orderStateUpdateDTO) {
        OmsOrder omsOrder = new OmsOrder();
        BeanUtils.copyProperties(orderStateUpdateDTO,omsOrder);
        omsOrderMapper.updateOrderStateById(omsOrder);

    }

    // 查看时间范围内的订单
    @Override
    public JsonPage<OrderListVO> listOrdersBetweenTimes(OrderListTimeDTO orderListTimeDTO) {
        // 过滤时间
        xxx(orderListTimeDTO);
        // 由于前端不能解析jwt，所以传过来的用户id是空的
        orderListTimeDTO.setUserId(getUserId());
        PageHelper.startPage(orderListTimeDTO.getPage(), orderListTimeDTO.getPageSize());

        List<OrderListVO> list = omsOrderMapper.selectOrderBetweenTimes(orderListTimeDTO);

        return JsonPage.restPage(new PageInfo<>(list));
    }

    private void xxx(OrderListTimeDTO orderListTimeDTO) {
        LocalDateTime startTime = orderListTimeDTO.getStartTime();
        LocalDateTime endTime = orderListTimeDTO.getEndTime();
        // 当有一个时间为null，则默认查询一个月内的订单
        if (startTime == null || endTime == null){
            startTime = LocalDateTime.now().minusMonths(1);
            endTime = LocalDateTime.now();
            orderListTimeDTO.setStartTime(startTime);
            orderListTimeDTO.setEndTime(endTime);
        }else {
            if (endTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()<
            startTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()){
                throw new CoolSharkServiceException(ResponseCode.BAD_REQUEST,"起始时间应该小于结束时间！");
            }
        }
    }

    @Override
    public OrderDetailVO getOrderDetail(Long id) {
        return null;
    }

    // 验证用户登录信息
    public CsmallAuthenticationInfo getUserInfo() {
        UsernamePasswordAuthenticationToken authenticationToken =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        if (authenticationToken == null){
            throw new CoolSharkServiceException(ResponseCode.NOT_FOUND,"您没有登录！");
        }
        CsmallAuthenticationInfo authenticationInfo = (CsmallAuthenticationInfo) authenticationToken.getCredentials();
        return authenticationInfo;
    }

    public Long getUserId() {
        return getUserInfo().getId();
    }
}
